package edu.cdnu.config;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;

import edu.cdnu.cache.RedisCacheManager;
import edu.cdnu.filter.MyFormAuthenticationFilter;
import edu.cdnu.realm.UserRealm;

/**
 * Shiro配置类
 * @author ASUS AsingZ
 */
@Configuration
@ConfigurationProperties(prefix="shiro")
public class ShiroAutoConfiguration {

	
	/**
	 * 加密方式
	 */
	private String hashAlgorithmName = "md5";
	/**
	 * 散列次数
	 */
	private int hashIterations = 1;
	/**
	 * 未登陆跳转
	 */
	private String loginUrl = "/index.html";
	/**
	 * 未授权跳转
	 */
	private String unauthorizedUrl = "/unauthorized.html";
	
	/**
	 * 允许的url
	 */
	private String[] anonUrls;
	/**
	 * 拦截的url
	 */
	private String[] authcUrls;
	
	
	/**
	 * 凭证匹配器
	 * @return
	 */
	@Bean
	public HashedCredentialsMatcher getHashedCredentialsMatcher() {
		HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
		// 注入加密方式
		credentialsMatcher.setHashAlgorithmName(hashAlgorithmName);
		// 注入散列次数
		credentialsMatcher.setHashIterations(hashIterations);
		return credentialsMatcher;
	}
	
	/**
	 * 声明userRealm
	 */
	@Bean
	public UserRealm userRealm(HashedCredentialsMatcher credentialsMatcher) {
		UserRealm userRealm = new UserRealm();
		// 注入凭证匹配器
		userRealm.setCredentialsMatcher(credentialsMatcher);
		return userRealm;
	}
	
	/**
	 * 声明安全管理器
	 */
	@Bean
	public SecurityManager securityManager(UserRealm userRealm,RedisCacheManager redisCacheManager,SessionManager sessionManager
			) { // ,CookieRememberMeManager cookieRememberMeManager 
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		// 注入realm
		securityManager.setRealm(userRealm);
		//注入CacheManager
		securityManager.setCacheManager(redisCacheManager);
		//注入SessionManager
		securityManager.setSessionManager(sessionManager);
		// 自动登录
//		securityManager.setRememberMeManager(cookieRememberMeManager);
		return securityManager;
	}
	
	/**
	 * 配置shiro的代理过滤器
	 * @return
	 */
	@Bean
	public FilterRegistrationBean<DelegatingFilterProxy> filterRegistrationBeanDelegatingFilterProxy() {
		// 创建注册器
		FilterRegistrationBean<DelegatingFilterProxy> registrationBean = new FilterRegistrationBean<>();
		// 创建过滤器
		DelegatingFilterProxy proxy = new DelegatingFilterProxy();
		// 设置过滤器的参数
		proxy.setTargetBeanName("shiroFilter");
		proxy.setTargetFilterLifecycle(true);
		// 注册
		registrationBean.setFilter(proxy);
		Collection<String> servletNames = new ArrayList<>();
		servletNames.add(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
		registrationBean.setServletNames(servletNames);
		
		//------------------------------设置过期时间
//		Map<String, String> initParameters = new HashMap<String, String>();
//		initParameters.put("serverSessionTimeout", "1800000");
//		initParameters.put("globalSessionTimeout", "1800000");
//		registrationBean.setInitParameters(initParameters);
		
		return registrationBean;
	}
	
	@Bean(value = "shiroFilter")
	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
		ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
		// 注入安全管理器
		factoryBean.setSecurityManager(securityManager);
		// 设置非登陆跳转的页面
		factoryBean.setLoginUrl(loginUrl);
		// 未授权的跳转页
		factoryBean.setUnauthorizedUrl(unauthorizedUrl);

		Map<String, String> filterChainDefinitionMap = new HashMap<>();
		
		//设置放行的url
		if(anonUrls!=null&&anonUrls.length>0) {
			for (String url : anonUrls) {
				filterChainDefinitionMap.put(url, "anon");
			}
		}
		//设置拦击的url
		if(authcUrls!=null&&authcUrls.length>0) {
			for (String url : authcUrls) {
				filterChainDefinitionMap.put(url, "authc");
			}
		}

		// 设置过滤器
		factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		Map<String, Filter> filters=new HashMap<>();
		filters.put("authc", new MyFormAuthenticationFilter());
		//重写authc过滤器
		factoryBean.setFilters(filters);
		
		return factoryBean;
	}
	
	
//	@Bean
//	public CookieRememberMeManager cookieRememberMeManager(SimpleCookie simpleCookie) {
//		CookieRememberMeManager cookieRememberMeManager=new CookieRememberMeManager();
//		cookieRememberMeManager.setCookie(simpleCookie);
//		return cookieRememberMeManager;
//	}
//	
//	@Bean
//	public SimpleCookie simpleCookie() {
//		SimpleCookie cookie = new SimpleCookie();
//		cookie.setName("simpleCookie");
//		cookie.setMaxAge(20000000);
//		return cookie;
//	}
	
	@Bean
	public PrincipalCollection principalCollection() {
		SimplePrincipalCollection principalCollection=new SimplePrincipalCollection();
		return principalCollection;
	}
	
	/****加入对注解的支持******/
	/**
	 * 
	 * @param securityManager
	 * @return
	 */
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
		return authorizationAttributeSourceAdvisor;
	}
	
	@Bean
	public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
		advisorAutoProxyCreator.setProxyTargetClass(true);
		return advisorAutoProxyCreator;
	}

	/**
	 ********************************************************************************** 
	 */
	
	
	
	
	
	/**
	 ********************************************************************************** 
	 */
	
	public String getHashAlgorithmName() {
		return hashAlgorithmName;
	}

	public void setHashAlgorithmName(String hashAlgorithmName) {
		this.hashAlgorithmName = hashAlgorithmName;
	}

	public int getHashIterations() {
		return hashIterations;
	}

	public void setHashIterations(int hashIterations) {
		this.hashIterations = hashIterations;
	}

	public String getLoginUrl() {
		return loginUrl;
	}

	public void setLoginUrl(String loginUrl) {
		this.loginUrl = loginUrl;
	}

	public String getUnauthorizedUrl() {
		return unauthorizedUrl;
	}

	public void setUnauthorizedUrl(String unauthorizedUrl) {
		this.unauthorizedUrl = unauthorizedUrl;
	}

	public String[] getAnonUrls() {
		return anonUrls;
	}

	public void setAnonUrls(String[] anonUrls) {
		this.anonUrls = anonUrls;
	}

	public String[] getAuthcUrls() {
		return authcUrls;
	}

	public void setAuthcUrls(String[] authcUrls) {
		this.authcUrls = authcUrls;
	}
}
